package pers.kw.server.service;

import java.math.BigDecimal;

import com.alibaba.fastjson.JSON;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pers.kw.dto.UpdateAcctBalanceReqDto;
import pers.kw.exceptions.BizException;
import pers.kw.goods.enums.GoodTypeEnum;
import pers.kw.protocol.R;
import pers.kw.server.dto.OrderReqDto;
import pers.kw.server.feign.AccountApiService;
import pers.kw.server.feign.StorageApiService;
import pers.kw.server.persist.dao.OrderDao;
import pers.kw.server.persist.dao.OrderDetailDao;
import pers.kw.server.persist.entity.OrderDO;
import pers.kw.server.persist.entity.OrderDetailDO;
import pers.kw.storage.dto.UpdateStorageReqDto;
import pers.kw.utils.DoWrapUtil;
import pers.kw.utils.SnowFlake;

import javax.annotation.Resource;

@Slf4j
@Service
public class OrderService {

    @Resource
    private OrderDao orderDao;

    @Resource
    private OrderDetailDao orderDetailDao;

    @Resource
    private AccountApiService accountApiService;

    @Resource
    private StorageApiService storageApiService;

    @Resource
    private ZnxNoticeService znxNoticeService;

    private static final String userNo = "12138";

    /**
     * 全局事务入口
     *
     * @param reqDto
     * @return
     */
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public String createOrder(OrderReqDto reqDto) {
        log.info("创建订单start...入参: {}", JSON.toJSONString(reqDto));
        long startTime = System.currentTimeMillis();

        //1.模拟异常，商品不存在
        if (!GoodTypeEnum.GOOD_TYPE_LIST.contains(reqDto.getGoodsNo())) {
            throw new BizException(String.format("商品[%s]不存在", reqDto.getGoodsNo()));
        }

        GoodTypeEnum goodTypeEnum = GoodTypeEnum.getGoodTypeByNo(reqDto.getGoodsNo());
        if (goodTypeEnum == null) {
            throw new BizException(String.format("商品[%s]不存在", reqDto.getGoodsNo()));
        }

        //生成订单编号
        String orderNo = SnowFlake.getSnowId();
        //计算订单总金额
        BigDecimal orderAmt = goodTypeEnum.getPrice().multiply(BigDecimal.valueOf(reqDto.getGoodsNum()));

        //创建订单
        OrderDO orderDO = new OrderDO();
        orderDO.setUserNo(userNo);
        orderDO.setOrderNo(orderNo);
        orderDO.setGoodsNum(reqDto.getGoodsNum());
        orderDO.setOrderAmt(orderAmt);
        DoWrapUtil.insert(orderDO, false, false);
        //订单明细
        OrderDetailDO orderDetailDO = new OrderDetailDO();
        orderDetailDO.setGoodsNo(reqDto.getGoodsNo());
        orderDetailDO.setOrderNo(orderNo);
        orderDetailDO.setGoodsNum(reqDto.getGoodsNum());
        orderDetailDO.setGoodsAmt(goodTypeEnum.getPrice());
        orderDetailDO.setOrderAmt(orderAmt);
        DoWrapUtil.insert(orderDetailDO, false, false);
        orderDao.save(orderDO);
        orderDetailDao.save(orderDetailDO);
        //2.扣减库存（模拟异常，库存不足）
        R<String> updateStorageResp = storageApiService.updateStorage(new UpdateStorageReqDto(
                reqDto.getGoodsNo(), reqDto.getGoodsNum(), ""
        ));
        if (!updateStorageResp.isOk()) {
            throw new BizException(updateStorageResp.getMsg());
        }

        //3.扣减账户余额 （模拟异常，余额不足）
        R<String> updateAcctBalanceResp = accountApiService.updateAcctBalance(
                new UpdateAcctBalanceReqDto(userNo, orderAmt)
        );
        if (!updateAcctBalanceResp.isOk()) {
            throw new BizException(updateAcctBalanceResp.getMsg());
        }

        //4.订单创建成功，发送站内信


        long endTime = System.currentTimeMillis();
        log.info("创建订单end...出参: {} ，耗时：{}ms", orderNo, endTime - startTime);
        return orderNo;
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateOrder(OrderReqDto reqDto) {
        log.info("修改订单start...入参: {}", JSON.toJSONString(reqDto));
        //修改订单
        //扣减库存
        //扣减账户余额
        log.info("修改订单[{}]end...", reqDto.getOrderNo());
    }
}
